import type { Metadata } from 'next'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { Bars } from '@/components/charts/bars'; import { LineChart } from '@/components/charts/line-chart'; import { Sparkline } from '@/components/charts/sparkline'; import { CompanyTable } from '@/components/company/company-table'; import { EventList } from '@/components/events/event-row'; import { EventTypeBadge } from '@/components/ui/badges'; import { Container, Empty, Note, PageHeader, Section, Stat, StatGrid } from '@/components/ui/section'; import { api, ApiError, safe } from '@/lib/api'; import { countryName } from '@/lib/countries'; import { fmtInt, fmtPctSigned, fmtScore } from '@/lib/format'; import { routes } from '@/lib/site'; import type { CompanyCard, IndustryDetailRaw } from '@/lib/types'; export const revalidate = 300; async function load(slug: string): Promise { try { return await api.industry(slug); } catch (e) { if (e instanceof ApiError && e.notFound) notFound(); throw e; } } export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise { const { slug } = await params; const d = await safe(api.industry(slug)); if (!d) return { title: 'Industry' }; return { title: `${d.name} — industry atlas`, description: `${d.name}: ${Array.isArray(d.companies) ? d.companies.length : d.companies} monitored companies, ${d.events_30d} structured events in 30 days, hiring momentum ${fmtPctSigned(d.hiring_momentum_30d)}.`, alternates: { canonical: `/industry/${slug}` } }; } export default async function IndustryPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params; const d = await load(slug); const companies: CompanyCard[] = Array.isArray(d.companies) ? d.companies : []; const count = Array.isArray(d.companies) ? d.companies.length : d.companies; const countries = d.countries ?? []; return ( Industry atlas {d.parent_slug && ( <> / {d.parent_slug.replace(/-/g, ' ')} )} } title={d.name} lede={d.description ?? `Monitored companies classified under ${d.name}.`} />
{d.series?.length > 1 ? ({ day: p.day, value: p.value })) }]} height={200} yZero /> : }
{countries.length ? ({ key: c.country, label: countryName(c.country), value: c.companies, href: routes.country(c.country) }))} /> : } {d.top_event_types?.length > 0 && (

Top event types: {d.top_event_types.map((t) => ( ))}

)}
{d.trending?.length ? (
    {d.trending.slice(0, 8).map((t) => (
  • {t.term} 0 ? 'text-positive' : 'text-ink-3'}`}>{fmtPctSigned(t.momentum, 0)}
  • ))}
) : ( )} Hiring: {d.hiring ? `${fmtInt(d.hiring.new_30d)} new and ${fmtInt(d.hiring.removed_30d)} no-longer-listed roles in 30 days across monitored careers pages.` : 'summary unavailable.'}
); }